Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
@opentelemetry/instrumentation
Advanced tools
Base class for node which OpenTelemetry instrumentation modules extend
The @opentelemetry/instrumentation package is part of the OpenTelemetry project, which aims to provide a unified and standardized observability framework for monitoring applications' performance and behavior. This particular package offers a way to automatically instrument code to collect telemetry data such as traces and metrics, making it easier to monitor and debug applications.
Automatic Instrumentation
Automatically instruments Node.js applications to collect telemetry data, such as tracing information for HTTP requests. This example shows how to set up the NodeTracerProvider and register the HttpInstrumentation to start collecting data.
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const provider = new NodeTracerProvider();
registerInstrumentations({
instrumentations: [
new HttpInstrumentation()
],
tracerProvider: provider,
});
Custom Instrumentation
Enables the creation of custom instrumentation for any library or application code not covered by the existing instrumentations. This example demonstrates how to extend the InstrumentationBase class to create a custom instrumentation.
const { InstrumentationBase } = require('@opentelemetry/instrumentation');
class MyCustomInstrumentation extends InstrumentationBase {
constructor() {
super('MyCustomInstrumentation');
}
init() {
// Custom initialization logic
}
}
Jaeger client is a package for distributed tracing in microservices architecture. It can be used to monitor and troubleshoot transactions in complex distributed systems. Compared to @opentelemetry/instrumentation, jaeger-client is more specific to the Jaeger backend, whereas OpenTelemetry provides a more vendor-neutral approach, allowing data to be exported to various backends including Jaeger.
npm install --save @opentelemetry/instrumentation
import {
InstrumentationBase,
InstrumentationConfig,
InstrumentationNodeModuleDefinition,
InstrumentationNodeModuleFile,
} from '@opentelemetry/instrumentation';
import type * as module_name_to_be_patched from 'module_name_to_be_patched';
export class MyPlugin extends InstrumentationBase {
constructor(config: InstrumentationConfig = {}) {
super('MyPlugin', VERSION, config);
}
/**
* Init method will be called when the plugin is constructed.
* It returns an `InstrumentationNodeModuleDefinition` which describes
* the node module to be instrumented and patched.
* It may also return a list of `InstrumentationNodeModuleDefinition`s if
* the plugin should patch multiple modules or versions.
*/
protected init() {
const module = new InstrumentationNodeModuleDefinition<typeof module_name_to_be_patched>(
'module_name_to_be_patched',
['1.*'],
this._onPatchMain,
this._onUnPatchMain,
);
// in case you need to patch additional files - this is optional
module.files.push(this._addPatchingMethod());
return module;
// you can also define more modules then just return an array of modules
// return [module1, module2, ....]
}
private _onPatchMain(moduleExports: typeof module_name_to_be_patched) {
this._wrap(
moduleExports,
'mainMethodName',
this._patchMainMethodName()
);
return moduleExports;
}
private _onUnPatchMain(moduleExports: typeof module_name_to_be_patched) {
this._unwrap(moduleExports, 'mainMethodName');
}
private _addPatchingMethod(): InstrumentationNodeModuleFile<typeof module_name_to_be_patched> {
const file = new InstrumentationNodeModuleFile<typeof module_name_to_be_patched>(
'module_name_to_be_patched/src/some_file.js',
this._onPatchMethodName,
this._onUnPatchMethodName,
);
return file;
}
private _onPatchMethodName(moduleExports: typeof module_name_to_be_patched) {
this._wrap(
moduleExports,
'methodName',
this._patchMethodName()
);
return moduleExports;
}
private _onUnPatchMethodName(moduleExports: typeof module_name_to_be_patched) {
this._unwrap(moduleExports, 'methodName');
}
private _patchMethodName(): (original) => any {
const plugin = this;
return function methodName(original) {
return function patchMethodName(this: any): PromiseOrValue<module_name_to_be_patched.methodName> {
console.log('methodName', arguments);
return original.apply(this, arguments);
};
};
}
private _patchMainMethodName(): (original) => any {
const plugin = this;
return function mainMethodName(original) {
return function patchMainMethodName(this: any): PromiseOrValue<module_name_to_be_patched.mainMethodName> {
console.log('mainMethodName', arguments);
return original.apply(this, arguments);
};
};
}
}
// Later
const myPLugin = new MyPlugin();
myPLugin.setTracerProvider(provider); // this is optional
myPLugin.setMeterProvider(meterProvider); // this is optional
myPLugin.enable();
// or use Auto Loader
import {
InstrumentationBase,
InstrumentationConfig,
} from '@opentelemetry/instrumentation';
import { Instrumentation } from '@opentelemetry/instrumentation';
export class MyPlugin extends InstrumentationBase {
constructor(config: InstrumentationConfig = {}) {
super('MyPlugin', VERSION, config);
}
private _patchOpen() {
return (original: OpenFunction): OpenFunction => {
const plugin = this;
return function patchOpen(this: XMLHttpRequest, ...args): void {
console.log('open', arguments);
return original.apply(this, args);
};
};
}
public enable() {
this._wrap(XMLHttpRequest.prototype, 'open', this._patchOpen());
}
public disable() {
this._unwrap(XMLHttpRequest.prototype, 'open');
}
}
// Later
const myPLugin = new MyPlugin();
myPLugin.setTracerProvider(provider);
myPLugin.setMeterProvider(meterProvider);
myPLugin.enable();
// or use Auto Loader
Successor of loading plugins through TracerProvider "plugins" option. It also supersedes PluginLoader for node. The old configurations usually looks like
const { NodeTracerProvider } = require('@opentelemetry/node');
const { B3Propagator } = require('@opentelemetry/propagator-b3');
const provider = new NodeTracerProvider({
plugins: {
http: { enabled: false },
},
});
provider.register({
propagator: new B3Propagator(),
});
const { WebTracerProvider } = require('@opentelemetry/web');
const { UserInteractionPlugin } = require('@opentelemetry/plugin-user-interaction');
const { XMLHttpRequestInstrumentation } = require('@opentelemetry/instrumentation-xml-http-request');
const { B3Propagator } = require('@opentelemetry/propagator-b3');
const provider = new WebTracerProvider({
plugins: [
new UserInteractionPlugin(),
new XMLHttpRequestInstrumentation({
ignoreUrls: [/localhost/],
propagateTraceHeaderCorsUrls: [
'http://localhost:8090',
],
}),
],
});
provider.register({
propagator: new B3Propagator(),
});
After change it will look like this - mixing plugins and instrumentations together All plugins will be bound to TracerProvider as well as instrumentations
const { B3Propagator } = require('@opentelemetry/propagator-b3');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { GraphQLInstrumentation } = require('@opentelemetry/instrumentation-graphql');
const { NodeTracerProvider } = require('@opentelemetry/node');
const tracerProvider = new NodeTracerProvider();
registerInstrumentations({
instrumentations: [
new UserInteractionPlugin(),
new XMLHttpRequestInstrumentation({
ignoreUrls: [/localhost/],
propagateTraceHeaderCorsUrls: [
'http://localhost:8090',
],
}),
],
meterProvider: meterProvider,
tracerProvider: tracerProvider,
});
tracerProvider.register({
propagator: new B3Propagator(),
});
const { B3Propagator } = require('@opentelemetry/propagator-b3');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
const { UserInteractionPlugin } = require('@opentelemetry/plugin-user-interaction');
const { WebTracerProvider } = require('@opentelemetry/web');
const tracerProvider = new WebTracerProvider();
registerInstrumentations({
instrumentations: [
new GraphQLInstrumentation(),
{
plugins: {
http: { enabled: false },
},
}
],
meterProvider: meterProvider,
tracerProvider: tracerProvider,
});
tracerProvider.register({
propagator: new B3Propagator(),
});
Apache 2.0 - See LICENSE for more information.
FAQs
Base class for node which OpenTelemetry instrumentation modules extend
The npm package @opentelemetry/instrumentation receives a total of 11,779,216 weekly downloads. As such, @opentelemetry/instrumentation popularity was classified as popular.
We found that @opentelemetry/instrumentation demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.